﻿CREATE PROCEDURE [dbo].[CheckPartyFlow] --проверка товародвижения по партии
(
	@PartyId int,						 --код стороки CA.GoodsDocLines
	@Qntty int,							 --проверяемый приход или отмена расхода (>0) или расход или отмена прихода(<0)
	@ChekDate smalldatetime, --дата проверки. Время должно быть 00:00:00
	@InputCount int OUTPUT,  --количество приходов по партии с датами больше или равно @ChekDate
	@OutputCount int OUTPUT  --количество расходов по партии с датами больше или равно @ChekDate
)
AS
DECLARE @strMsg nvarchar(500), @intErrCode int
DECLARE @datRestDate smalldatetime, @intCount int, @intCountAfterCheckDate int
DECLARE @intRestTtl int, @intPartyRest int, @intRestToDate int, @datCheckNextDay smalldatetime
DECLARE @strBarCode char(12)

DECLARE @tblCheck TABLE (
Id float NOT NULL, 
TurnQntty int NOT NULL, --оборот 
RollQntty int NULL			--нарастающий итог
PRIMARY KEY CLUSTERED (	[Id] ASC ) )

SET NOCOUNT ON

IF (@PartyId Is Null) OR (@Qntty Is Null) OR (@ChekDate Is Null)
BEGIN
	SELECT @intErrCode = 1, @strMsg = 'Неправильные параметры в вызове процедуры ' + Object_Name(@@Procid) + ' !'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

SET @ChekDate = dbo.NormalizeDate(@ChekDate)

SELECT @datCheckNextDay = dateadd(day,1,@ChekDate), @intRestToDate = 0

SELECT @intRestTtl = sum(G.Qntty), @intCount = count(*),
@intRestToDate = sum(CASE WHEN D.DocDate < @datCheckNextDay THEN G.Qntty ELSE 0.0 END),	  --остаток на дату проверки включительно
@intCountAfterCheckDate = sum(CASE WHEN D.DocDate >= @datCheckNextDay THEN 1 ELSE 0 END),
@InputCount = sum(CASE WHEN D.DocDate >= @ChekDate AND G.Qntty > 0 THEN 1 ELSE 0 END),
@OutputCount = sum(CASE WHEN D.DocDate >= @ChekDate AND G.Qntty < 0 THEN 1 ELSE 0 END)
FROM CA.GoodsDocLines G INNER JOIN CA.Documents D ON G.DocId = D.Id 
WHERE G.PartyId = @PartyId 

IF @intRestTtl < 0 
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 601, 
	@strMsg = 'Расчетный текущий остаток по партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') меньше нуля!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

IF @intCount < 1 AND @Qntty < 0 
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 602, 
	@strMsg = 'По партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') не было прихода!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

IF @intRestToDate < 0 
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 603, 
	@strMsg = 'Остаток по партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') на дату ' + convert(varchar(20), @ChekDate, 4) + ' меньше нуля!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

SELECT @intPartyRest = RestQntty FROM CD.Parties WHERE Id = @PartyId
IF @intPartyRest < 0 
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 604, 
	@strMsg = 'Хранимый текущий остаток по партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') меньше нуля!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END
--	@strMsg = 'Остатки по партии (' + cast(@intPartyRest as varchar(20)) + ') не соответствуют сумме по товародвижению (' + cast(@intSumGoodsFlow as varchar(20)) + ')!'

IF @intRestTtl <> @intPartyRest
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 605, 
	@strMsg = 'По партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') хранимый текущий остаток (' + cast(@intPartyRest as varchar(20)) + ') не совпадает с расчетным текущим остатком (' + cast(@intRestTtl as varchar(20)) + ')!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

IF ((@intRestTtl + @Qntty) < 0) AND @Qntty < 0 
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 606, 
	@strMsg = 'По партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') расчетный остаток (' + cast(@intRestTtl as varchar(20)) + ') меньше чем расход (' + cast(@Qntty as varchar(20)) + ')!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

IF @intCountAfterCheckDate <= 0 OR @Qntty > 0  RETURN 0 --не было товародвижения после даты проверки или проверяется приход

INSERT INTO @tblCheck (Id, TurnQntty)
SELECT  floor(cast(D.DocDate as float)), sum(G.Qntty) 
FROM CA.GoodsDocLines G INNER JOIN CA.Documents D ON G.DocId = D.Id 
WHERE G.PartyId = @PartyId AND D.DocDate >= @datCheckNextDay
GROUP BY floor(cast(D.DocDate as float))  --оборот по суткам
--расчет нарастающего итога
UPDATE @tblCheck SET @intRestToDate = @intRestToDate + TurnQntty, RollQntty = @intRestToDate

SELECT TOP 1 @datRestDate = cast(Id as smalldatetime)
FROM @tblCheck WHERE RollQntty < 0

IF @datRestDate IS NOT NULL
BEGIN
	SELECT @strBarCode = BarCode FROM CD.Parties WHERE Id = @PartyId
	SELECT @intErrCode = 607, 
	@strMsg = 'Остаток по партии ' + @strBarCode + '(' + cast(@PartyId as varchar(20)) + ') на дату ' + convert(varchar(20), @datRestDate, 4) + ' c учетом изменений меньше нуля!'
	RAISERROR (@strMsg, 11, 1)
	RETURN @intErrCode
END

RETURN 0




















